(function (window) {
  const PENDING = 'pending';
  const RESOLVED = 'resolved';
  const REJECTED = 'rejected';
  
  // 通过类自定义promise
  class PromiseClass {
    // 构造器
    constructor(executor){
      const self = this;
      self.status = PENDING;
      self.data = undefined;
      self.callbacks = [];
  
      function resolved(value) {
        // 多次调用resolved方法返回
        if (self.status !== PENDING) return
    
        self.status = RESOLVED;
        self.data = value
        if (self.callbacks.length > 0) {
          setTimeout(() => {
            self.callbacks.forEach(cbs => {
              cbs.onResolved(value)
            })
          })
        }
      }
  
      function rejected(reason) {
        // 多次调用rejected方法返回
        if (self.status !== PENDING) return
    
        self.status = REJECTED;
        self.data = reason;
        if (self.callbacks.length > 0) {
          setTimeout(() => {
            self.callbacks.forEach(cbs => {
              cbs.onRejected(reason)
            })
          })
        }
      }
  
      try {
        executor(resolved, rejected)
      } catch (err) {
        rejected(err)
      }
    }

    // 实例then方法
    then = function (onResolved, onRejected) {
      const self = this;
    
      onResolved = typeof onResolved === 'function' ? onResolved : value => value;
      onRejected = typeof onRejected === 'function' ? onRejected : reason => {
        throw reason
      };
    
      // 返回新的promise
      return new Promise((resolve, reject) => {
      
        // 封装的回调函数
        function handle(callback) {
          try {
            const result = callback(self.data)
            if (result instanceof Promise) {  //返回值是promise
              result.then(value => resolve(value), reason => reject(reason))
            } else {  //返回值不是promise，只是一个普通的值
              resolve(result)
            }
          } catch (err) {  //捕获到错误
            reject(err)
          }
        }
      
        if (this.status === 'resolved') {   //状态为resolved
          setTimeout(() => {
            handle(onResolved)
          })
        } else if (this.status === 'rejected') {   //状态为rejected
          setTimeout(() => {
            handle(onRejected)
          })
        } else {  //状态为pending
          this.callbacks.push({
            onResolved(value) {
              handle(onResolved)
            },
            onRejected(reason) {
              handle(onRejected)
            }
          })
        }
      })
    };


    // 实例catch方法
    catch = function (onRejected) {
      return this.then(undefined, onRejected)
    };

    // 静态resolve方法
    static resolve = function (value) {
      return new Promise((resolve, reject) => {
        if (value instanceof Promise) {
          value.then(resolve, reject)
        } else {
          resolve(value)
        }
      })
    };

    // 静态reject方法
    static reject = function (reason) {
      return new Promise((resolve, reject) => {
        reject(reason)
      })
    };

    // 静态all方法
    static all = function (promise) {
      return new Promise((resolve, reject) => {
        let resolvedCount = 0;
        const values = new Array(promise.length)
        promise.forEach((p, index) => {
          p.then(
            value => {
              resolvedCount++;
              values[index] = value
              if (resolvedCount === promise.length) {  //都成功
                resolve(values)
              }
            },
            reason => reject(reason)
          )
        })
      })
    };

    // 静态race方法
    static race = function (promise) {
      return new Promise((resolve, reject) => {
        promise.forEach(p => {
          p.then(resolve, reject)
        })
      })
    };


    // 自定义静态resolveDelay方法，具有延时效果
    static resolveDelay = function (value, time) {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          if (value instanceof Promise) {
            value.then(resolve, reject)
          } else {
            resolve(value)
          }
        },time)
      })
    };

    // 自定义静态rejectDelay方法，具有延时效果
    static rejectDelay = function (reason, time) {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          reject(reason)
        }, time)
      })
    };
  }
  
  // 将类挂载到window上
  window.PromiseClass = PromiseClass
})(window)
